package cgDb

import (
	"errors"
	"fmt"
	"time"

	"gitee.com/zzzcommon/common-go/cgModel"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func MysqlConnection(dbConfig cgModel.DbConfig) (*gorm.DB, error) {
	conn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		dbConfig.User,
		dbConfig.Password,
		dbConfig.Host,
		dbConfig.Port,
		dbConfig.Schema,
	)
	_db, err := gorm.Open(mysql.Open(conn))
	if err != nil {
		return _db, err
	}
	_db.Set("gorm:table_options", "ENGINE=InnoDB")
	_mysql, err := _db.DB()
	if _mysql != nil {
		_mysql.SetConnMaxLifetime(time.Minute * time.Duration(10))
		_mysql.SetMaxOpenConns(5)
		_mysql.SetMaxIdleConns(1)
	}
	// defer _db.Close()
	return _db, err
}

type DbHandler func(db *gorm.DB) error

type GetDbFn func() (*gorm.DB, error)

func DbInstance(fn GetDbFn, handler DbHandler) error {
	if handler == nil {
		return errors.New("db handler is nil")
	}
	_db, err := fn()
	if err != nil {
		return err
	}
	return handler(_db)
}

func DbQuery(fn GetDbFn, dest interface{}, sql string, values ...interface{}) error {
	var err error = nil
	err = DbInstance(fn, func(db *gorm.DB) error {
		rs := db.Raw(sql, values...)
		if dest == nil || rs.Error != nil {
			return rs.Error
		}
		srs := rs.Scan(dest)
		return srs.Error
	})
	return err
}

func DbExecute(fn GetDbFn, dest interface{}, sql string, values ...interface{}) error {
	var err error = nil
	err = DbInstance(fn, func(db *gorm.DB) error {
		rs := db.Exec(sql, values...)
		if dest == nil || rs.Error != nil {
			return rs.Error
		}
		srs := rs.Scan(dest)
		return srs.Error
	})
	return err
}
